package com.acmen.easyapi.parse;

import com.acmen.easyapi.annotation.ReqParam;
import com.acmen.easyapi.factory.impl.DefaultClassAliasFactory;
import com.acmen.easyapi.model.ReqParamNode;
import com.acmen.easyapi.util.ParamNameDiscoverer;
import com.acmen.easyapi.util.AnnotationUtil;
import com.acmen.easyapi.util.SpringContextUtil;
import com.acmen.easyapi.util.StringUtil;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;


/**
 * 请求头部解释器
 *
 * @author acmen
 */
@Component
public class RequestHeaderParser{
    /**
     * 获取RequestHeaderParser的单例对象
     *
     * @return RequestHeaderParser对象
     */
    public static final RequestHeaderParser getInstance() {
        return SpringContextUtil.getBean(RequestHeaderParser.class);
    }

    /**
     * 根据方法生成请求参数节点列表
     *
     * @param method 待解析的方法
     * @return 请求参数节点列表
     */
    public List<ReqParamNode> createParamNodes(Method method) {
               List<List<Annotation>> parameterAnnotations = AnnotationUtil.getParameterAnnotations(method);
        Type[] parameterTypes = method.getParameterTypes();
        String[] parameterNames = ParamNameDiscoverer.getParameterNames(method);

        // 查找请求映射注解
        RequestMapping reqMapping = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);

        // 创建请求头参数节点
        List<ReqParamNode> paramNodes = createParamNodesForRequestHeader(parameterNames, parameterTypes, parameterAnnotations);

        // 如果请求映射注解的 consumes 属性长度大于0
        if (reqMapping.consumes().length > 0) {
            // 创建参数节点
            ReqParamNode paramNode = new ReqParamNode();
            paramNode.setName("Content-Type");
            paramNode.setLabel("媒体格式类型");
            paramNode.setRequired(true);
            paramNode.setExample(reqMapping.consumes()[0]);
            paramNode.setType(String.class.getName());
            paramNode.setTypeAlias(DefaultClassAliasFactory.getAlias(String.class));

            // 如果请求映射注解的 consumes 属性长度为1
            if (reqMapping.consumes().length == 1) {
                paramNode.addNote("必需值：" + reqMapping.consumes()[0]);
            } else {
                String content = null;
                for (String consume : reqMapping.consumes()) {
                    if (content == null) {
                        content = consume;
                    } else {
                        content += "|" + consume;
                    }
                }
                paramNode.addNote("必需值：" + content);
            }
            paramNodes.add(paramNode);
        } else {
            // 遍历参数注解列表
            for (int i = 0; i < parameterTypes.length; i++) {
                // 查找请求体注解
                RequestBody requestBody = AnnotationUtil.getAnnotation(parameterAnnotations.get(i), RequestBody.class);
                if (requestBody != null) {
                    // 创建参数节点
                    ReqParamNode paramNode = new ReqParamNode();
                    paramNode.setName("Content-Type");
                    paramNode.setLabel("媒体格式类型");
                    paramNode.setRequired(true);
                    paramNode.setExample("application/json");
                    paramNode.setType(String.class.getName());
                    paramNode.setTypeAlias(DefaultClassAliasFactory.getAlias(String.class));
                    paramNode.addNote("必需值：application/json");
                    paramNodes.add(paramNode);
                    break;

                }
            }
        }

        // 遍历请求映射注解的 headers 属性
        for (String header : reqMapping.headers()) {
                       String[] headers = header.split("=");
            if (headers.length >= 2) {
                // 创建参数节点
                ReqParamNode paramNode = new ReqParamNode();
                paramNode.setName(headers[0]);  // 设置参数名
                paramNode.setLabel(headers[0]);  // 设置参数标签
                paramNode.setRequired(true);  // 设置参数为必需值
                paramNode.setExample("application/json");  // 设置参数示例值
                paramNode.setType(String.class.getName());  // 设置参数类型
                paramNode.setTypeAlias(DefaultClassAliasFactory.getAlias(String.class));  // 设置参数类型别名
                paramNode.addNote("必需值：" + headers[1]);  // 添加参数说明
                paramNodes.add(paramNode);  // 将参数节点添加到参数集合
            }

        }

        return paramNodes;
    }


    /**
     * 根据参数注解生成请求参数节点列表
     *
     * @param parameterNames 参数名称
     * @param parameterTypes 参数类型
     * @param parameterAnnotations 参数注解
     * @return 请求参数节点列表
     */
    private List<ReqParamNode> createParamNodesForRequestHeader(String[] parameterNames, Type[] parameterTypes, List<List<Annotation>> parameterAnnotations) {
                List<ReqParamNode> paramNodes = new ArrayList<>(); // 创建一个存储ReqParamNode对象的列表
        for (int i = 0; i < parameterTypes.length; i++) { // 遍历参数数组
            Type parameterType = parameterTypes[i]; // 获取当前参数类型
            RequestHeader requestHeader = AnnotationUtil.getAnnotation(parameterAnnotations.get(i), RequestHeader.class); // 获取参数注解中的RequestHeader注解
            if (requestHeader == null) { // 如果参数没有RequestHeader注解，则跳过当前循环
                continue;
            }
            ReqParam reqParam = AnnotationUtil.getAnnotation(parameterAnnotations.get(i), ReqParam.class); // 获取参数注解中的ReqParam注解
            ReqParamNode paramNode = new ReqParamNode(); // 创建一个ReqParamNode对象
            String paramName = StringUtil.isEmpty(requestHeader.value()) ? requestHeader.name() : requestHeader.value(); // 获取参数名，如果RequestHeader注解的value属性为空，则使用name属性作为参数名
            if(StringUtil.isEmpty(paramName)){ // 如果参数名为空，则使用参数索引作为参数名
                paramName = parameterNames[i];
            }
            paramNode.setName(paramName); // 设置参数名
            paramNode.setLabel(reqParam!=null?reqParam.label():""); // 如果ReqParam注解不为空，则设置参数标签，否则设置为空字符串
            String dataType = parameterType.getTypeName(); // 获取参数类型的全限定名
            int idx = dataType.lastIndexOf("."); // 获取类型名称中最后一个点的索引
            dataType = dataType.substring(idx + 1); // 获取类型名称中的类名部分
            paramNode.setType(dataType); // 设置参数类型
            if (reqParam != null) { // 如果ReqParam注解不为空
                paramNode.setRequired(reqParam.required()); // 设置参数是否必填
                paramNode.setRequiredGroup(reqParam.requiredGroup()); // 设置参数所属必填组
                if(reqParam.maxLength() > 0 ){ // 如果ReqParam注解的maxLength属性大于0
                    paramNode.setMaxLength(reqParam.maxLength()); // 设置参数的最大长度
                }
                paramNode.setExample(reqParam.example()); // 设置参数的示例值
                paramNode.addNote(reqParam.note()); // 给参数添加注释
            }
            paramNodes.add(paramNode); // 将参数对象添加到列表中
        }
        return paramNodes; // 返回存储ReqParamNode对象的列表

    }
}
